Показано с 1 по 6 из 6

Тема: [MZ] Сборник рецептов для добавления «ЭкшОна» в игру (и некоторые размышления)

Древовидный режим

Предыдущее сообщение Предыдущее сообщение   Следующее сообщение Следующее сообщение
  1. #3
    Бывалый Аватар для Darchan Kaen
    Информация о пользователе
    Регистрация
    17.06.2013
    Адрес
    Одесса
    Сообщений
    851
    Записей в дневнике
    3
    Репутация: 47 Добавить или отнять репутацию

    По умолчанию

    Спойлер 2. Практическая часть:

    Тут будет «сборник рецептов», представляющих собой функции, сохраненные в переменные мейкера. Часть из них можно использовать сами по себе, часть требует наличия других связанных функций. Повторюсь, при желании, все из этого можно вынести в отдельный плагин…по сути, это самый оптимальный вариант работы.

    Большая часть кода практически использовалась в игре “ALWBAW”, ее же можно рассматривать как демо-версию – игра не зашифрована, ее можно открыть редактором (подбросив файл проекта MZ); если будете открывать – особый интерес представляют первые три «технические» карты и Общие события. Игру можно найти на данном форуме, на Светлой полосе, на Юнионе.
    Если «рецепт» в реальной игре не тестировался – это будет указано отдельно.
    Демо-игра также использует логику «сопартиец-как-патрон», что в рамках данного туториала рассматриваться не будет.

    В существенной части рецептов используется применение скрипта в Маршруте эвента и тот факт, что на скорость исполнения маршрута влияет частота эвента. Также используется возможность хранения и записи текста в Примечании эвента. Кроме того, для ряда рецептов (прыжок, платформы) используется задание регионов на карте – во всех примерах корректным является регион с номером «1» (это тоже можно менять).

    У каждого эвента-врага специальным образом заполнено Примечание и две страницы – первая, активируемая лок. переключателем «A» активная и вторая, активируемая лок. переключателем «B» не активная (враг уничтожен).
    У эвентов-"пулек" и эвентов-"бомб" - три страницы, первая пустая не активная (но уже с нужной графикой!), вторая и третья как у эвентов-врагов

    Номера функций в примерах кода взяты из игры, вы можете ставить любые. Код приводится в «сжатом» варианте – гарантированно влезает в команду «Скрипт» на MZ. Скриншотов не будет.
    Код, как и логику что он реализует, может быть не оптимальна.

    Спойлер Рецепт №1. «Прыжок с проверкой допустимости конечной точки»:

    Цель:
    Игрок прыгает на N-клеток вперед в сторону, которую повернут лицом (это называется «направление» в контексте мейкера) и только в том случае, если конечная точка допустима для приземления (чтоб не оказаться в стене, яме, итд). Направление передается из вызывающего кода.

    Логика:
    Согласно направлению и дальности прыжка, нужно узнать является ли конечная точка допустимым местом приземления. Для этого, исходя из направления, рассчитываются координаты корректной точки и проверяется ее номер ее региона.
    В случае, если конечная точка нам подходит, то так как прыжок работает по разнице координат, мы получаем текущие координаты игрока, вычисляем разницу с конечными координатами и вызываем для игрока встроенную функцию прыжка по вычисленным значениям. В коде также вызывается дрожь экрана и SE-звук, причем отдельный звук в случаях прыжка и отказа.

    Код функции Прыжка:
    Код:
    $gameVariables.setValue(10, (direction) => {
    let jumpRadius = 3; let playerEndpointCoords = [];
    if(8 === direction){ playerEndpointCoords = [$gamePlayer._x, $gamePlayer._y - jumpRadius];
    }else if(6 === direction){ playerEndpointCoords = [$gamePlayer._x + jumpRadius, $gamePlayer._y];
    }else if(4 === direction){ playerEndpointCoords = [$gamePlayer._x - jumpRadius, $gamePlayer._y];
    }else if(2 === direction){ playerEndpointCoords = [$gamePlayer._x, $gamePlayer._y + jumpRadius];
    }
    let playerEndpointRegionId = $gameMap.regionId(playerEndpointCoords[0], playerEndpointCoords[1]);
    if(1 === playerEndpointRegionId){
    let jumpCoordX = playerEndpointCoords[0] - $gamePlayer._x;
    let jumpCoordY = playerEndpointCoords[1] - $gamePlayer._y;
    if(undefined !== jumpCoordX && undefined !== jumpCoordY){
    $gamePlayer.jump(jumpCoordX, jumpCoordY);
    $gameScreen.startShake(7, 7, 15); AudioManager.playSe({ name: 'Earth1', volume: 60, pitch: 100, pan: 0 });
    }else{ AudioManager.playSe({ name: 'Buzzer1', volume: 60, pitch: 100, pan: 0 }); }
    }else{ AudioManager.playSe({ name: 'Buzzer1', volume: 60, pitch: 100, pan: 0 }); }
    });
    Что можно улучшить:
    Можно задать динамическую дальность прыжка, храня «радиус» в отдельной переменной. Можно сделать так, что в случае некоррктности конечной клетки, проверяется корректность предыдущий…и игрок прыгает хоть как-то. Можно хранить стартовые (до-прыжковые) координаты игрока в отдельной переменной.


    Спойлер Рецепт №2. «Клонирование эвента с его последующей активацией»:

    Цель:
    Создать новый эвент программно, по образцу уже существующего. При этом существующий эвент «не активен», т.е. первая страница пуста, а для работы он требует включеный локальный переключатель «A». При этом новый эвент создается по конкретным координатам с конкретным направлением. Id эвента для копирования, необходимые координаты и направление передаются из вызывающего кода.

    Логика:
    Копируем эвент, задаем ему новый случайный Id (цифры 1000 и 500 произвольны и исходят из кол-во ОБЫЧНЫХ, не клонированных, эвентов на карте), вставляем его в массивы эвентов игровые объектов $dataMap и $gameMap (для второго предварительно нужно создать новый «игровой» эвент), задаем новому эвенту направление, перемещаем в координаты, включаем у него «активный» локальный переключатель и обновляем графику всех эвентов на карте (сцене), тем самым делая клонированный эвент видимым.

    Код функции Клонирования:
    Код:
    $gameVariables.setValue(5, (eventToCloneId, cloneInCoordX, cloneInCoordY, cloneInDirection) => {
    let eventToCloneData = $dataMap.events[eventToCloneId]; 
    let clonedEventData = {...eventToCloneData};
    let newId = eventToCloneId + Math.floor(Math.random() * 1000 + 500); 
    if($dataMap.events.length < newId){ $dataMap.events.length = newId; }
    $dataMap.events[newId] = clonedEventData;
    let clonedMapEvent = new Game_Event(this._mapId, clonedEventData.id);
    clonedMapEvent._direction = cloneInDirection;
    clonedMapEvent.locate(cloneInCoordX, cloneInCoordY);
    $gameMap._events.push(clonedMapEvent);
    $dataMap.events[$dataMap.events.length - 1].id = newId; 
    $gameMap._events[$gameMap._events.length - 1]._eventId = newId;
    $gameSelfSwitches.setValue([$gameMap._mapId, newId, 'A'], true);
    SceneManager._scene._spriteset.createCharacters();
    });
    Что можно улучшить:
    Вероятно, можно улучшить генерацию случайного Id для нового эвента, введя доп. проверки на наличие таких Id.


    Спойлер Рецепт №3. «Понижение ХП игрока, урон по игроку»:

    Цель:
    Программного снижать ХП игрока (точнее, первого персонажа-лидера, в партии).

    Логика:
    Получаем объект игрока (лидера партии), меняем ХП с разрешением смерти.

    Код функции Снижения ХП:
    Код:
    $gameVariables.setValue(9, () => {
    let player = $gameParty.leader();
    let decrValue = -1;
    let canKO = true;
    this.changeHp(player, decrValue, canKO);
    });
    Что можно улучшить:
    Можно сделать, что бы величина уменьшения ХП передавалась в функцию снаружи и не была константой.


    Спойлер Рецепт №4. «Шипы»:

    Цель:
    Получить эвент, циклически меняющий свое состояние (фазы) и графику, при некоторых состояниях себя наносящий урон игроку, что находится на эвенте или проходит через него…т.е. наши любимые шипы. Желательно – без параллельных событий и «мучений» с графикой и маршрутом эвента.

    Логика:
    Эвент под персонажем, фиксированный.
    У эвента четыре страницы (они же стостояния-фазы), первая не требует локальные переключатели, следующие требуют включения «A», «B», «C».
    У эвента нормальная скорость и максимальная частота, у каждой страницы своя графика шипов.
    У каждой страницы задан маршрут, а именно:
    1) Первая страница – ждать 30 секунд и выполнить скрипт для включения лок. Переключателя «A».
    2) Вторая страница – ждать 30 секунд и выполнить скрипт для включения лок. Переключателя «B» с выключением лок. переключателя «A».
    3) Третья страница – выполнить код урона шипов для маршрута, ждать 30 секунд и выполнить скрипт для включения лок. переключателя «C» с выключением лок. переключателей «A» и «B».
    4) Четвертая страница – выполнить код урона шипов для маршрута, ждать 30 секунд и выполнить скрипт для выключения лок. переключателей «A», «B» и «C».
    Третья и четвертые страницы, кроме маршрута, активируются от касания игрока и выполняют специальный скрипт (урон игроку и показ анимации).
    Логика скрипта в маршруте – проверка координат игрока и если совпадают с координатами эвента, то урон игроку и анимация.

    Код в маршрурте, для переключения страницы-состояния (маршрут Повторяется, код должен быть одной строкой - но форум "поломал"):
    Код:
    //Первая страница:
    $gameSelfSwitches.setValue([$gameMap._mapId, this._eventId, 'A'], true);
    //Вторая страница:
    $gameSelfSwitches.setValue([$gameMap._mapId, this._eventId, 'A'], false); $gameSelfSwitches.setValue([$gameMap._mapId, this._eventId, 'B'], true);
    //Третья страница:
    $gameSelfSwitches.setValue([$gameMap._mapId, this._eventId, 'A'], false); $gameSelfSwitches.setValue([$gameMap._mapId, this._eventId, 'B'], false); $gameSelfSwitches.setValue([$gameMap._mapId, this._eventId, 'C'], true);
    //Четвертая страница:
    $gameSelfSwitches.setValue([$gameMap._mapId, this._eventId, 'A'], false); $gameSelfSwitches.setValue([$gameMap._mapId, this._eventId, 'B'], false); $gameSelfSwitches.setValue([$gameMap._mapId, this._eventId, 'C'], false);
    Код в маршруте эвента, на фазах урона (3 и 4 страницы):
    Код:
    let spikeDamage = $gameVariables.value(14); spikeDamage(this);
    Код Урона шипов для 3-й и 4-й страниц эвента:
    Код:
    let damagePlayer = $gameVariables.value(9); 
    $gameTemp.requestAnimation([$gamePlayer], 1);
    damagePlayer();
    Код функции Урона шипов для маршрута:
    Код:
    $gameVariables.setValue(14, (spikeEvent) => {
    if(spikeEvent._x === $gamePlayer._x && spikeEvent._y === $gamePlayer._y){ 
    let damagePlayer = $gameVariables.value(9); 
    $gameTemp.requestAnimation([$gamePlayer], 1);
    damagePlayer(); 
    }
    });
    Что можно улучшить:
    Не знаю, может вы подскажите.


    Спойлер Рецепт №5. «Движущиеся платформы»:

    Цель:
    Движущаяся эвент-платформа, на которую игрок может стать, и которая «красиво» транспортирует игрока в заданную точку.

    Логика:
    Эвент под персонажем.
    У эвента две страницы, в маршруте одной задается движение в нужную сторону, в маршруте другой – возврат к исходной точке; вторая страница включается лок. переключателем «A».
    Скорость нормальная, частота максимальная, графика на страницах может быть одинаковая / разная.
    Маршрут (маршрут Повторяется):
    1) Выключается проходимость.
    2) Ожидание 120 фреймов.
    3) Включается проходимость.
    4) …ставится нужное кол-во шагов, для достижения конечной точки…
    5) Выполняется скрипт для включения / выключения лок. переключателя «A» (в зависимости от страницы).
    Также каждая страница, кроме маршрута, активируется от касания игрока и выполняет скрипт.
    Логика скрипта на странице эвента – получаем объект эвента текущей платформы, задаем его координаты, задаем Схему движения, вызываем Функцию платформы и передаем ей это как аргументы.
    Логика функции Платформы – запрет прыжка, определение маршрута движения исходя из Схемы движения, движение пока не платформа не коснется корректного региона (под номером «1»), прыжок игрока на клетку в которую уперлась платформа, включение прыжка.

    Код в маршруте, для переключения страницы:
    Код:
    //Первая страница
    $gameSelfSwitches.setValue([$gameMap._mapId, this._eventId, 'A'], true);
    //Вторая страница
    $gameSelfSwitches.setValue([$gameMap._mapId, this._eventId, 'A'], false);
    Код в странице эвента:
    Код:
    let movePlatformWithPlayer = $gameVariables.value(13);
    let currentPlatform = $gameMap.event(5);
    let originCoords = [7, 8];
    let movePattern = 'DOWN-UP';
    movePlatformWithPlayer(currentPlatform, originCoords[0], originCoords[1], movePattern);
    Код функции Платформы для страницы эвента:
    Код:
    $gameVariables.setValue(13, (platformEvent, originX, originY, movePattern) => {
    $gameSwitches.setValue(2, false);
    let shiftByPatternX = 0; let shiftByPatternY = 0;
    if('UP-DOWN' === movePattern){ shiftByPatternY = 1;
    }else if('DOWN-UP' === movePattern){ shiftByPatternY = -1;
    }else if('LEFT-RIGHT' === movePattern){ shiftByPatternX = 1;
    }else if('RIGHT-LEFT' === movePattern){ shiftByPatternX = -1;
    }
    let nextTileX = platformEvent._x + shiftByPatternX; let nextTileY = platformEvent._y + shiftByPatternY; 
    let nextTileRegionId = $gameMap.regionId(nextTileX, nextTileY); 
    $gamePlayer._walkAnime = false;
    if(1 !== nextTileRegionId){
    platformEvent._x += shiftByPatternX; platformEvent._y += shiftByPatternY; 
    $gamePlayer._x += shiftByPatternX; $gamePlayer._y += shiftByPatternY;
    }else{
    $gamePlayer.jump(shiftByPatternX, shiftByPatternY);
    $gamePlayer._walkAnime = true;
    platformEvent._x = originX; platformEvent._y = originY;
    $gameSwitches.setValue(2, true);
    }
    });
    Что можно улучшить:
    В принципе, хотелось бы отвязаться от ручного задания координат в скрипте эвента – но способа я не нашел.


    Спойлер Рецепт №6. «Жив ли враг»:

    Цель:
    Узнать, является ли целевой эвент врагом и если да – есть у него еще ХП. Id врага-эвента задается извне.

    Логика:
    В каждом эвенте, который мы хотим использовать в качестве «врага» в своей АБС, в примечании пишем текст:
    {"type": "ENEMY", "hp": 3, "countVarId": 26}
    То есть, задаем объект с характеристиками:
    type – тип;
    hp – хп;
    countVarId – номер пеменной, в которую плюсуется +1 при уничтожении врага.
    Логика кода проверки – получаем Примечание нужного эвента (по его Id), парсим и читаем Примечание, находим и сравниваем ХП. Если ХП ноль и менее, или тип врага не тот, возвращаем false; иначе – true.

    Код функции Проверки ХП врага:
    Код:
    $gameVariables.setValue(2, (enemyEvent) => {
    let enemyData = $dataMap.events[enemyEvent._eventId].note; 
    if(0 === enemyData.length){ return false; }
    let enemyDataObj = JSON.parse(enemyData);
    let enemyHp = parseInt(enemyDataObj.hp);
    if(enemyHp <= 0 || 'ENEMY' !== enemyDataObj.type){
    return false;
    }else{
    return true;
    }
    });
    Что можно улучшить:
    Если типов врагов много, можно сделать доп. проверки.


    Спойлер Рецепт №7. «Уменьшение ХП врага»:

    Цель:
    Уменьшение характ-ки ХП эвента-врага. Id врага-эвента задается извне, как и урон.

    Логика:
    Получаем Примечание нужного эвента (по его Id), парсим и читаем Примечание, уменьшаем ХП, записываем обратно в Примечание эвента.
    Если ХП в результате меньше 0, то показываем на врага анимацию, включаем его «побежденный» переключатель «B», делая его тем самым неактивным, и приплюсовываем к переменной для кол-ва уничтоженных врагов единицу (если номер переменной равен 0, он игнорируется мейкером).
    ХП возвращается из ф-ии, т.к. это нужно для "бомбы".

    Код функции Уменьшения ХП врага:
    Код:
    $gameVariables.setValue(3, (enemyEvent, damageValue = 1) => {
    let enemyData = $dataMap.events[enemyEvent._eventId].note;
    if(0 === enemyData.length){ return false; }
    let enemyDataObj = JSON.parse(enemyData);
    let enemyHp = parseInt(enemyDataObj.hp);
    if(0 === enemyHp ){ return false; } 
    enemyHp -= damageValue;
    enemyDataObj.hp = enemyHp;
    $dataMap.events[enemyEvent._eventId].note = JSON.stringify(enemyDataObj);
    if(enemyHp <= 0){ 
    if('ENEMY' === enemyDataObj.type){ $gameTemp.requestAnimation([enemyEvent], 58); }
    $gameSelfSwitches.setValue([$gameMap._mapId, enemyEvent._eventId, 'B'], true);
    let countVarId = parseInt(enemyDataObj.countVarId); $gameVariables.setValue( countVarId, ($gameVariables.value(countVarId) + 1) );
    }
    return enemyHp; 
    });
    Что можно улучшить:
    Проверку по ХП. Возможно, добавить в «объект врага» кроме переменной – включение какого-то переключателя, это может быть полезно для Боссов.


    Спойлер Рецепт №8. «Удар игроком врага в ближнем бою»:

    Цель:
    Возможность для игрока атаковать эвент, находящийся в небольшой радиусе с ним, уменьшая его ХП.

    Логика:
    Логика делится на две части:
    1) Получения массива координат, в которых будет проходить поиска врагов; это и есть дальность и «радиус» удара; тут он не только перед игроком, но еще и по диагонали влево и вправо – для удобства. Массивы высчитывается исходя их координат игрока и его направления.
    2) По найденному массиву координат проходимся циклом, записываем его в массив найденных врагов. После чего проходимся уже по нему и для каждого найденного врага, проверяем жив ли он, и если да – наносим урон по эвенту-врагу и проигрываем анимацию.
    Перед вызовом скрипта с кодом атаки в ближнем бою, опционально, можно проиграть анимацию средствами команд мейкера.

    Код атаки врага в ближнем бою:
    Код:
    let getCoordsList = $gameVariables.value(1); let isEnemyyAlive = $gameVariables.value(2)
    let changeEnemyHP = $gameVariables.value(3);
    let coordsList = getCoordsList($gamePlayer); 
    let enemiesList = [];
    for(let n = 0; n < coordsList.length; n++){
    let currentEnemy = $gameMap.eventsXy(coordsList[n][0], coordsList[n][1]);
    if(currentEnemy.length > 0){
    enemiesList.push(currentEnemy[0]);
    }
    } 
    enemiesList.forEach(enemy => { 
    if(true === isEnemyyAlive(enemy)){
    $gameTemp.requestAnimation([enemy], 1); 
    changeEnemyHP(enemy); 
    }
    });
    Код функции Получения массива координат перед игроком:
    Код:
    $gameVariables.setValue(1, (player) => {
    let direction = player._direction;
    let coordsList = [];
    if(8 === direction){
    coordsList = [ [player._x - 1, player._y - 1], [player._x, player._y - 1], [player._x + 1, player._y - 1] ];
    }else if(6 === direction){
    coordsList = [ [player._x + 1, player._y - 1], [player._x + 1, player._y], [player._x + 1, player._y + 1] ];
    }else if(4 === direction){
    coordsList = [ [player._x - 1, player._y - 1], [player._x - 1, player._y], [player._x - 1, player._y + 1] ];
    }else if(2 === direction){
    coordsList = [ [player._x - 1, player._y + 1], [player._x, player._y + 1], [player._x + 1, player._y + 1] ];
    }
    return coordsList;
    });
    Что можно улучшить:
    Можно сделать несколько видов оружия ближнего боя и, в зависимости от выбранного оружия, менять массив координат для урона (оружие бьет вокруг, бьет с дальностью 2 клетки, бьет букой «Г», итд).



    Спойлер Рецепт №9. «Удар врагом игрока в ближнем бою»:

    Цель:
    Эвент-враг атакует игрока, находящегося рядом, понижая его ХП.

    Логика:
    Логика схожа с логикой удара игроком эвента.
    Сначала, исходя из координат атакующего эвента, получаем массив возможных координат атаки (функция в Рецепте №9).
    После чего для каждого варианта координат сверяем, совпадают ли они с координатами игрока и если да, то проигрываем на игрока анимации и снижаем его ХП. Опционально, в зависимости от направления эвента, проигрывается анимация «взмаха» оружием.
    Все это делает эвент-враг функцией, которую вызываем в маршруте (например: повторяющиеся шаг к игроку и вызов функции).
    Мне показалось, что оптимальная частота здесь не максимальная, а высокая.

    Код для маршрута:
    Код:
    let meleeEnemyAttack = $gameVariables.value(11); meleeEnemyAttack(this);
    Код функции Атаки врагом игрока в ближнем бою:
    Код:
    $gameVariables.setValue(11, (enemyEvent) => {
    let getCoordsList = $gameVariables.value(1);
    let damagePlayer = $gameVariables.value(9);
    let coordsList = getCoordsList(enemyEvent);
    let direction = enemyEvent._direction;
    for(let n = 0; n < coordsList.length; n++){
    if(coordsList[n][0] === $gamePlayer._x && coordsList[n][1] === $gamePlayer._y){
    if(8 === direction){ $gameTemp.requestAnimation([enemyEvent], 122); 
    }else if(6 === direction){ $gameTemp.requestAnimation([enemyEvent], 125); 
    }else if(4 === direction){ $gameTemp.requestAnimation([enemyEvent], 124); 
    }else if(2 === direction){ $gameTemp.requestAnimation([enemyEvent], 123); 
    }
    $gameTemp.requestAnimation([$gamePlayer], 1); 
    damagePlayer();
    }
    } 
    });
    Что можно улучшить:
    Если будет несколько типов врагов ближнего боя, для них можно сделать разные массивы координат (разные дальность и радиус удара).



    Спойлер Рецепт №10. «Выстрел игрока и/или врага»:

    Цель:
    При активации скрипта, перед игроком / врагом появляется эвент-«пулька» и движется N-ое количество шагов по направлению игрока и / или врага.

    Логика:
    Логика делится на логику «выстрела» и логику «пульки»
    Логика выстрела - получаем координаты клетки перед игроком / врагом, исходя из его направления, в которые будет перемещено клонируемый эвент-«пулька» и клонируем эвент-«пульку».
    Логика «пульки» - проходимый фиксированный эвент, с Примечанием {"type": "BULLET", "hp": 7, "countVarId": 0} , в котором ХП обозначает дальность движения. Страница «A» активна, на ней задан маршрут с высокой скоростью и максимальной частотой. В маршруте только выполняется скрипт. Логика функции вызываемого скрипта – каждый шаг «пульки» проверяется, есть ли на ее текущих координатах эвенты и игрок, если есть – анимация на них и им урон, и в любом случае – урон самой «пульке»!

    Код функции Клонирования эвента-«пульки»:
    Код:
    const EVENT_TO_SPAWN_ID = $gameVariables.value(27);
    let getFaceSideCoords = $gameVariables.value(4);
    let spawnEvent = $gameVariables.value(5); 
    
    let direction = $gamePlayer._direction; // для стреляющего врага тут указывается его направление!
    let coordsForSpawn = getFaceSideCoords($gamePlayer); //для стреляющего врага тут указывается его эвент!!
    
    spawnEvent(EVENT_TO_SPAWN_ID, coordsForSpawn[0], coordsForSpawn[1], direction);
    Код функции Получения координат перед игроком / врагом:
    Код:
    $gameVariables.setValue(4, (playerOrEvent) => {
    let coords = [];
    let direction = playerOrEvent._direction;
    if(8 === direction){
    coords[0] = playerOrEvent._x;
    coords[1] = playerOrEvent._y - 2;
    }else if(2 === direction){
    coords[0] = playerOrEvent._x;
    coords[1] = playerOrEvent._y + 2;
    }else if(4 === direction){
    coords[0] = playerOrEvent._x - 2;
    coords[1] = playerOrEvent._y;
    }else if(6 === direction){
    coords[0] = playerOrEvent._x + 2;
    coords[1] = playerOrEvent._y;
    } 
    return coords
    });
    Код для маршрута «пульки»:
    Код:
    let moveBulletEvent = $gameVariables.value(6); moveBulletEvent(this);
    Код функции Движения «пульки»:
    Код:
    $gameVariables.setValue(6, (bulletEvent) => { let isEnemyAlive = $gameVariables.value(2); let decreaseHp = $gameVariables.value(3);
    let enemiesOnWay = $gameMap.eventsXy(bulletEvent._x, bulletEvent._y);
    if(enemiesOnWay.length > 1){
    let enemyOnWay = enemiesOnWay.filter(enemy => enemy._eventId !== bulletEvent._eventId)[0]; 
    if(true === isEnemyAlive(enemyOnWay)){ $gameTemp.requestAnimation([enemyOnWay], 1); } 
    decreaseHp(enemyOnWay, 2); $gameSelfSwitches.setValue([$gameMap._mapId, bulletEvent._eventId, 'B'], true); 
    }
    if(bulletEvent._x === $gamePlayer._x && bulletEvent._y === $gamePlayer._y){ $gameTemp.requestAnimation([$gamePlayer], 1); 
    let damagePlayer = $gameVariables.value(9); damagePlayer();
    $gameSelfSwitches.setValue([$gameMap._mapId, bulletEvent._eventId, 'B'], true); 
    } decreaseHp(bulletEvent);
    let direction = bulletEvent._direction; 
    if(8 === direction){ bulletEvent._y -= 1;
    }else if(2 === direction){ bulletEvent._y += 1;
    }else if(4 === direction){ bulletEvent._x -= 1;
    }else if(6 === direction){ bulletEvent._x += 1;
    }
    });
    Что можно улучшить:
    Если будет несколько видом дальнобойного оружия, можно изменить проходимость (в данном коде «пулька» самоуничтожается после дамага по игроку / врагу), можно сделать несколько эвентов-«пулек» с разной дальностью (ХП) и скоростью. Возможно, копировать «пульку» не перед лицом стреляющего, а в других координатах (над, под, 2-3 пульки).


    Спойлер Рецепт №11. «Тикающая бомба»:

    Цель:
    При активации скрипта, на месте игрока / врага создается эвент-бомба, «взрывающийся» через некоторое количество времени.

    Логика:
    Логика схожа с логикой выстрела, т.к. для клонирования используется специальный объект-«часовая бомба», у которой тоже маршрут со скриптом, и которая тоже наносит себе же урон. При достижении 1 ХП и происходит «взрыв», нанося урон всем (и игроку, и эвентам-врагам) в заданном радиусе.
    А еще бобма прыгает в процессе "тикания".

    Код для «призыва бомбы»:
    Код:
    $gameVariables.setValue(15, (enemyEvent) => {
    const EVENT_TO_SPAWN_ID = $gameVariables.value(28);
    let getFaceSideCoords = $gameVariables.value(4);
    let spawnEvent = $gameVariables.value(5); 
    let direction = enemyEvent._direction;
    let coordsForSpawn = getFaceSideCoords(enemyEvent);
    spawnEvent(EVENT_TO_SPAWN_ID, coordsForSpawn[0], coordsForSpawn[1], direction);
    AudioManager.playSe( { name: 'Bite', volume: 90, pitch: 100, pan: 0 } );
    });
    Код для маршрута «бомбы»:
    Код:
    let tickBombEvent = $gameVariables.value(7); tickBombEvent(this);
    Код функции Тикания «бомбы»:
    Код:
    $gameVariables.setValue(7, (bombEvent) => { let isEnemyAlive = $gameVariables.value(2); let decreaseHp = $gameVariables.value(3);
    let hp = decreaseHp(bombEvent); bombEvent.jump(0, 0); 
    let bombRadius = [ [bombEvent._x - 1, bombEvent._y - 1], [bombEvent._x, bombEvent._y - 1], [bombEvent._x + 1, bombEvent._y - 1],
    [bombEvent._x - 1, bombEvent._y], [bombEvent._x, bombEvent._y], [bombEvent._x + 1, bombEvent._y],
    [bombEvent._x - 1, bombEvent._y + 1], [bombEvent._x, bombEvent._y + 1], [bombEvent._x + 1, bombEvent._y + 1], ];
    let enemiesList = [];
    if(1 === hp){
    $gameTemp.requestAnimation([bombEvent], 66); 
    for(let n = 0; n < bombRadius.length; n++){
    let currentEnemy = $gameMap.eventsXy(bombRadius[n][0], bombRadius[n][1]);
    if(currentEnemy.length > 0){
    enemiesList.push(currentEnemy[0]);
    }
    if(bombRadius[n][0] === $gamePlayer._x && bombRadius[n][1] === $gamePlayer._y){
    let damagePlayer = $gameVariables.value(9); damagePlayer();
    $gameTemp.requestAnimation([$gamePlayer], 1); 
    }
    } console.log('enemiesList:', enemiesList);
    enemiesList.forEach(enemy => { 
    if(true === isEnemyAlive(enemy)){
    $gameTemp.requestAnimation([enemy], 1); 
    decreaseHp(enemy, 3); 
    }
    });
    }
    });
    Что можно улучшить:
    Не знаю, мне просто нравится как это работает.


    Спойлер Рецепт №12. «Вывод информации»:

    А тут не будет рецепта, т.к. с графической частью я так и не разобрался.

    Для этого лучше использовать плагин: dirge, Galv, Orange…
    Я же в демо-игре просто в переменные записывал ХП, патроны и выбранное оружие и показывал в сообщении (ну и цветом экрана + графикой сопартийцев).
    Как справедливо заметил Петр, ставить параллельное событие с изменением цвета экрана – не очень мудро…но я так и делал. =)

    Чтоб рецепт не был пустым, вот то единственное что я смог найти и сделать для отрисовки окон изнутри мукера:
    Код:
    var rect = new Rectangle(25, 25, 400, 400);
    var win = new Window_Base(rect);
    SceneManager._scene.addChild(win);
    win.drawTextEx('\\C[18]HP\\V[24]', 125, 150, 350, 'center');
    Может быть, вы это сможете довести до вменяемого вида и как-то использовать.
    В реальной игре это не тестировалось.


    Спойлер Рецепт №DKR. «Бонус»:

    1) Изменение графики эвента:
    Код:
    $gameMap.event(n).setImage(graphicImage, graphicIndex);
    где graphicImage – название файла в кавычках без расширения, graphicIndex – номер графики персонажа в файле; нумерация начинается с 0.

    2) Синхронизация движения эвентов A и B (количество эвентов не ограничено), чтоб двигались по одинаковому маршруту:
    Код:
    let eventA = $gameMap.event(1);
    let eventB = $gameMap.event(2);
    let moveRouteA = eventA._moveRoute;
    eventB.forceMoveRoute(eventA._moveRoute);
    1, 2 - номера эвентов.
    В реальной игре это не тестировалось.


    Что еще можно сделать:
    «Не вошедшее»
    Бумеранг. Отражение «пулек» обратно в точку их старта. Телепорт-«крюк».
    И все, на что вам хватит фантазии и силы в борьбе с мукером.

    Последний раз редактировалось Darchan Kaen; 31.03.2022 в 09:06. Причина: Дополнение о страницах эвентов-врагов

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Метки этой темы

Социальные закладки

Социальные закладки

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •  
[MZ] Сборник рецептов для добавления «ЭкшОна» в игру (и некоторые размышления)